﻿
package com.giantflyingsaucer
{
	import flash.events.*;
	import flash.net.XMLSocket;	
	import flash.system.*;

	
	public class GFSServerXMLSocketManager extends EventDispatcher
	{
        private var socket:XMLSocket;
		private var username:String = "";
		private var hostname:String;
		private var port:int = 843;
				
		private static const LOGIN:String = "LOGIN"; 	
		private static const LOGIN_NO_PASSWORD:String = "LOGIN_NO_PASSWORD";
		
		private static const CREATE_ACCOUNT:String = "CREATE_ACCOUNT";
		private static const DELETE_ACCOUNT:String = "DELETE_ACCOUNT";
		private static const DISABLE_ACCOUNT:String = "DISABLE_ACCOUNT";
		private static const ENABLE_ACCOUNT:String = "ENABLE_ACCOUNT";				
		private static const CHECK_IF_ACCOUNT_DISABLED:String = "CHECK_IF_ACCOUNT_DISABLED";						

		private static const ROOM_LIST:String = "ROOM_LIST";	
		private static const USER_LIST:String = "USER_LIST";
		
		private static const CREATE_ROOM:String = "CREATE_ROOM";
		private static const JOIN_ROOM:String = "JOIN_ROOM";
		private static const LEAVE_ROOM:String = "LEAVE_ROOM";				

		private static const SYSTEM_BROADCAST:String = "SYSTEM_BROADCAST";
		private static const BROADCAST_ROOM:String = "BROADCAST_ROOM";
		private static const BROADCAST_GAME:String = "BROADCAST_GAME";	
		private static const BROADCAST_USER_LEFT_ROOM:String = "BROADCAST_USER_LEFT_ROOM";			
		private static const BROADCAST_USER_DISCONNECTED:String = "BROADCAST_USER_DISCONNECTED";		
		private static const BROADCAST_PRIVATE_MESSAGE:String = "BROADCAST_PRIVATE_MESSAGE";
		private static const BROADCAST_USER_JOINED_ROOM:String = "BROADCAST_USER_JOINED_ROOM";				
		
		private static const UPDATE_PROPERTY:String = "UPDATE_PROPERTY";
		private static const DELETE_PROPERTY:String = "DELETE_PROPERTY";
		private static const INSERT_PROPERTY:String = "INSERT_PROPERTY";	
		private static const READ_PROPERTY:String = "READ_PROPERTY";			
		private static const UPDATE_GLOBAL_PROPERTY:String = "UPDATE_GLOBAL_PROPERTY";
		private static const DELETE_GLOBAL_PROPERTY:String = "DELETE_GLOBAL_PROPERTY";
		private static const INSERT_GLOBAL_PROPERTY:String = "INSERT_GLOBAL_PROPERTY";	
		private static const READ_GLOBAL_PROPERTY:String = "READ_GLOBAL_PROPERTY";					
		private static const READ_SESSION_PROPERTY:String = "READ_SESSION_PROPERTY";	
		private static const INSERT_SESSION_PROPERTY:String = "INSERT_SESSION_PROPERTY";			
		private static const UPDATE_SESSION_PROPERTY:String = "UPDATE_SESSION_PROPERTY";
				
		private static const SHUTDOWN_SERVER:String = "SHUTDOWN_SERVER";			
		private static const GET_ALL_DB_USERNAMES:String = "GET_ALL_DB_USERNAMES";		
		private static const GET_USER_COUNT:String = "GET_USER_COUNT";						
		private static const GET_USER_LAST_LOGIN_DATE:String = "GET_USER_LAST_LOGIN_DATE";				
		private static const GET_ALL_USER_PROPERTY_NAMES:String = "GET_ALL_USER_PROPERTY_NAMES";						
		private static const GET_ALL_GLOBAL_PROPERTY_NAMES:String = "GET_ALL_GLOBAL_PROPERTY_NAMES";						
		private static const GET_USERS_IP:String = "GET_USERS_IP";						

		private static const KICK:String = "KICK";
		private static const BLOCK:String = "BLOCK";
		private static const UNBLOCK:String = "UNBLOCK";
		
		private static const CHANGE_PASSWORD:String = "CHANGE_PASSWORD";
		private static const FORGOT_ADMIN_PASSWORD:String = "FORGOT_ADMIN_PASSWORD";
		
		private static const MAP_DATA:String = "MAP_DATA";
		private static const CONNECTED:String = "CONNECTED";
		private static const USERPROPERTIES:String = "USERPROPERTIES";
		
		private static const BOARD_LIST:String = "BOARD_LIST";
		private static const CREATE_BOARD:String = "CREATE_BOARD";
		private static const JOIN_BOARD:String = "JOIN_BOARD";

		private static const BROADCAST_STATUS:String = "BROADCAST_STATUS";
		private static const PHONG:String = "PHONG";
		
		public function GFSServerXMLSocketManager(hostName:String, socketPort:int)
		{
			try
			{
				port = socketPort;
				hostname = hostName;
				//Security.loadPolicyFile("xmlsocket://" + hostName + ":843")
	            socket = new XMLSocket();
	            configureListeners(socket);	            
			}
			catch(err:Error)
			{
				trace(err);
			}
		}				
		
		public function connect():void
		{
			try
			{
				socket.connect(hostname, port);			
			}
			catch(err:Error)
			{
				trace(err);
			}			
		}		
		
		public function disconnect():void
		{
			try
			{
				socketSend("QUIT");
				//socket.close();			
				dispatchEvent(new GFSServerEvent(GFSServerEvent.NOT_CONNECTED));
			}
			catch(err:Error)
			{
				trace(err);
			}			
		}
		
		public function shutdownServer():void
		{
			socketSend(SHUTDOWN_SERVER);
		}
		
		public function getAllDBUsernames():void
		{
			socketSend(GET_ALL_DB_USERNAMES);
		}				
		
		public function retrieveAdminPassword():void
		{
			socketSend(FORGOT_ADMIN_PASSWORD);
		}						
				
		public function getOnlineUserCount():void
		{
			socketSend(GET_USER_COUNT);
		}						
		
		public function getUsersIP(userName:String):void
		{
			socketSend(GET_USERS_IP + "~" + userName);
		}		
				
		public function getServerVersion():void
		{
			socketSend(GFSServerEvent.SERVER_VERSION);
		}		
		
		public function getUserLastLogin(userName:String):void
		{
			socketSend(GET_USER_LAST_LOGIN_DATE + "~" + userName);		}								
		
		public function getAllUserPropertyNames(userName:String):void
		{
			socketSend(GET_ALL_USER_PROPERTY_NAMES + "~" + userName);
		}
		
		public function getAllGlobalPropertyNames():void
		{
			socketSend(GET_ALL_GLOBAL_PROPERTY_NAMES);
		}												
		
		public function disableAccount(userName:String):void
		{
			socketSend(DISABLE_ACCOUNT + "~" + userName);
		}						
		
		public function enableAccount(userName:String):void
		{
			socketSend(ENABLE_ACCOUNT + "~" + userName);
		}								
		
		public function kick(userName:String):void
		{
			socketSend(KICK + "~" + userName);
		}		
		
		public function block(userName:String):void
		{
			socketSend(BLOCK + "~" + userName);
		}		
		
		public function unblock(userName:String):void
		{
			socketSend(UNBLOCK + "~" + userName);
		}				
		
		public function changePassword(userName:String, newPassword:String):void
		{
			socketSend(CHANGE_PASSWORD + "~" + userName + "~" + newPassword);
		}
		
		public function checkIfAccountIsDisabled(userName:String):void
		{
			socketSend(CHECK_IF_ACCOUNT_DISABLED + "~" + userName);			
		}
		
		public function login(userName:String, password:String):void
		{
			this.username = userName;
			socketSend(LOGIN + "~" + username + "~" + password);
		}	
		
		public function loginNoPassword(userName:String):void
		{
			this.username = userName;
			socketSend(LOGIN_NO_PASSWORD + "~" + username);
		}			
		
		public function sendGameMessage(messageText:String):void
		{
			socketSend(BROADCAST_GAME + "~" + messageText);
		}
		
		public function createAccount(userName:String, password:String):void
		{
			socketSend(CREATE_ACCOUNT + "~" + userName + "~" + password);
		}	
		
		public function deleteAccount(userName:String):void
		{
			socketSend(DELETE_ACCOUNT + "~" + userName);
		}			
		
		public function readGlobalProperty(propertyName:String):void
		{
			socketSend(READ_GLOBAL_PROPERTY + "~" + propertyName);
		}		
		
		public function insertGlobalProperty(propertyName:String, propertyValue:String):void
		{
			socketSend(INSERT_GLOBAL_PROPERTY + "~" + propertyName + "~" + propertyValue);
		}		
		
		public function updateGlobalProperty(propertyName:String, propertyValue:String):void
		{
			socketSend(UPDATE_GLOBAL_PROPERTY + "~" + propertyName + "~" + propertyValue);
		}
		
		public function deleteGlobalProperty(propertyName:String):void
		{
			socketSend(DELETE_GLOBAL_PROPERTY + "~" + propertyName);
		}				
		
		public function readProperty(userName:String, propertyName:String):void
		{
			socketSend(READ_PROPERTY + "~" + userName + "~" + propertyName);
		}		
		
		public function insertProperty(propertyName:String, propertyValue:String):void
		{
			socketSend(INSERT_PROPERTY + "~" + propertyName + "~" + propertyValue);
		}		
		
		public function updateProperty(propertyName:String, propertyValue:String):void
		{
			socketSend(UPDATE_PROPERTY + "~" + propertyName + "~" + propertyValue);
		}
		
		public function deleteProperty(userName:String, propertyName:String):void
		{
			socketSend(DELETE_PROPERTY + "~" + userName + "~" + propertyName);
		}		
		
		public function updateSessionProperty(propertyName:String, propertyValue:String):void
		{
			socketSend(UPDATE_SESSION_PROPERTY + "~" + propertyName + "~" + propertyValue);
		}
		
		public function readSessionProperty(propertyName:String):void
		{
			socketSend(READ_SESSION_PROPERTY + "~" + propertyName);
		}				
		
		public function insertSessionProperty(propertyName:String, propertyValue:String):void
		{
			socketSend(INSERT_SESSION_PROPERTY + "~" + propertyName + "~" + propertyValue);
		}		
		
		public function sendRoomMessage(messageText:String):void
		{
			socketSend(BROADCAST_ROOM + "~" + messageText);
		}
		
		public function sendSystemBroadcast(messageText:String):void
		{
			socketSend(SYSTEM_BROADCAST + "~" + messageText);
		}		
		
		public function sendPrivateMessage(toUsername:String, messageText:String):void
		{
			if(StringUtils.trim(toUsername).length <= 0)
				return;
				
			if(StringUtils.trim(messageText).length <= 0)
				return;				
				
			socketSend(BROADCAST_PRIVATE_MESSAGE + "~" + toUsername + "~" + messageText);
		}		
		
		public function createRoom():void
		{
			socketSend(CREATE_ROOM + "~" + username);			
		}
		
		public function joinRoom(roomName:String):void
		{
			socketSend(JOIN_ROOM + "~" + username + "~" + roomName);			
		}		
		
		public function leaveRoom():void
		{
			socketSend(LEAVE_ROOM + "~" + username);			
		}		
		
		public function requestUserList():void
		{
			socketSend(USER_LIST);			
		}
		
		public function requestRoomList():void
		{
			socketSend(ROOM_LIST);			
		}		
		
		public function isConnected():Boolean
		{
			return socket.connected;
		}
		
		
		
		private function socketSend(str:String):void
		{
			try
			{
				//socket.send(Base64.encode(StringUtils.stripTags(str)));	
				socket.send(str);	
			}
			catch(err:Error)
			{
				trace(err);
			}						
		}
		
		private function configureListeners(dispatcher:IEventDispatcher):void
		{
			dispatcher.addEventListener(Event.CLOSE, closeHandler);
			dispatcher.addEventListener(Event.CONNECT, connectHandler);
			dispatcher.addEventListener(DataEvent.DATA, dataHandler);
			dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
		}
		
		private function closeHandler(event:Event):void
		{
			dispatchEvent(new GFSServerEvent(GFSServerEvent.NOT_CONNECTED));
			trace("closeHandler: " + event);
		}
		
		private function connectHandler(event:Event):void
		{
			trace("connectHandler: " + event);
			dispatchEvent(new GFSServerEvent(GFSServerEvent.CONNECTED,"","",CONNECTED));
		}
		
		private function dataHandler(event:DataEvent):void
		{
			var arr:Array = null;
			trace("dataHandler: " + event.data);			
			trace("dataHandler: " + Base64.decode(event.data));
			event.data = event.data;
			
			//chat_txt.text += event.data + "\n";
			
			try
			{			
				if(event.data == GFSServerEvent.LOGIN_OK)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.LOGIN_OK));
					return;
				}			
				if(event.data == GFSServerEvent.LOGIN_ERROR_USER_ALREADY_LOGGED_IN)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.LOGIN_ERROR_USER_ALREADY_LOGGED_IN));
					return;
				}			
				if(event.data == GFSServerEvent.LOGIN_ERROR_WRONG_PASSWORD_OR_USERNAME)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.LOGIN_ERROR_WRONG_PASSWORD_OR_USERNAME));
					return;
				}	
				if(event.data == GFSServerEvent.SESSION_TIMED_OUT)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.SESSION_TIMED_OUT));
					return;
				}	
				if(event.data == GFSServerEvent.PASSWORD_CHANGED)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.PASSWORD_CHANGED));
					return;
				}							
				if(event.data == GFSServerEvent.PASSWORD_CHANGED_ERROR)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.PASSWORD_CHANGED_ERROR));
					return;
				}											
				if(event.data == GFSServerEvent.CONNECTION_LIMIT_HIT)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.CONNECTION_LIMIT_HIT));
					return;
				}							
				if(event.data == GFSServerEvent.ACCOUNT_CREATED)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.ACCOUNT_CREATED));
					return;
				}			
				if(event.data == GFSServerEvent.ACCOUNT_CREATION_ERROR_USERNAME_EXISTS)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.ACCOUNT_CREATION_ERROR_USERNAME_EXISTS));
					return;
				}			
				if(event.data == GFSServerEvent.ACCOUNT_CREATION_ERROR_UNSPECIFIED)
				{
					dispatchEvent(new GFSServerEvent(GFSServerEvent.ACCOUNT_CREATION_ERROR_UNSPECIFIED));
					return;
				}							
				if(StringUtils.contains(event.data, BROADCAST_USER_DISCONNECTED))			
				{								
					arr = event.data.split("~");
													
					dispatchEvent(new GFSServerEvent(GFSServerEvent.USER_DISCONNECTED, arr[1]));				
					return;
				}																								
				if(StringUtils.contains(event.data, BROADCAST_USER_LEFT_ROOM))			
				{								
					arr = event.data.split("~");
													
					dispatchEvent(new GFSServerEvent(GFSServerEvent.USER_LEFT_ROOM, arr[1]));				
					return;
				}																					
				if(StringUtils.contains(event.data, ROOM_LIST))			
				{								
					arr = event.data.split("~");
					var rooms:String = StringUtils.remove(arr.toString(), "ROOM_LIST,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_ROOM_LIST, username, "", rooms));				
					return;
				}																		
				if(StringUtils.contains(event.data, BROADCAST_ROOM))
				{				
					arr = event.data.split("~");
					
					// Check if the message is a newly created room
					if(arr[2] == GFSServerEvent.ROOM_CREATED)
					{
						dispatchEvent(new GFSServerEvent(GFSServerEvent.ROOM_CREATED, arr[1]));
						return;
					}
								
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_ROOM_MESSAGE, arr[1], arr[2]));
					return;
				}															
				if(StringUtils.contains(event.data, BROADCAST_USER_JOINED_ROOM))
				{				
					arr = event.data.split("~");
					dispatchEvent(new GFSServerEvent(GFSServerEvent.USER_JOINED_ROOM, arr[1]));
					return;
				}			
				if(StringUtils.contains(event.data, USER_LIST))
				{				
					arr = event.data.split("~");
					var users:String = StringUtils.remove(arr.toString(), "USER_LIST,", false)
	
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_USER_LIST, username, "", users));
					return;
				}						
				if(StringUtils.contains(event.data, GFSServerEvent.ACCOUNT_CREATED))
				{				
					arr = event.data.split("~");
												
					dispatchEvent(new GFSServerEvent(GFSServerEvent.ACCOUNT_CREATED, username));
					return;
				}			
				if(StringUtils.contains(event.data, BROADCAST_PRIVATE_MESSAGE))
				{				
					arr = event.data.split("~");
												
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_PRIVATE_MESSAGE, arr[1], arr[2]));
					return;
				}
				if(StringUtils.contains(event.data, BROADCAST_GAME))
				{				
					arr = event.data.split("~");
												
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_GAME_MESSAGE, arr[1], arr[2]));
					return;
				}	
				if(StringUtils.contains(event.data, READ_SESSION_PROPERTY))
				{				
					arr = event.data.split("~");
												
					var strSessionProperty:String = StringUtils.remove(arr.toString(), "READ_SESSION_PROPERTY,", false)												
												
					dispatchEvent(new GFSServerEvent(GFSServerEvent.READ_SESSION_PROPERTY_RESULT, "", "", strSessionProperty));
					return;
				}				
				if(StringUtils.contains(event.data, SYSTEM_BROADCAST))
				{				
					arr = event.data.split("~");
												
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_SYSTEM_BROADCAST_MESSAGE, "", arr[1]));
					return;
				}			
				if(StringUtils.contains(event.data, GFSServerEvent.INCOMING_USER_COUNT))
				{				
					arr = event.data.split("~");
												
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_USER_COUNT, "", "", arr[1]));
					return;
				}											
				if(StringUtils.contains(event.data, GFSServerEvent.READ_PROPERTY_RESULT))
				{				
					arr = event.data.split("~");

					var strProperty:String = StringUtils.remove(arr.toString(), "READ_PROPERTY,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.READ_PROPERTY_RESULT, "", "", strProperty));
					return;
				}								
				if(StringUtils.contains(event.data, GFSServerEvent.READ_GLOBAL_PROPERTY_RESULT))
				{				
					arr = event.data.split("~");

					var strGlobalProperty:String = StringUtils.remove(arr.toString(), "READ_GLOBAL_PROPERTY,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.READ_GLOBAL_PROPERTY_RESULT, "", "", strGlobalProperty));
					return;
				}												
				if(StringUtils.contains(event.data, GFSServerEvent.INCOMING_DB_USERS_LIST))
				{				
					arr = event.data.split("~");

					var dbUsersList:String = StringUtils.remove(arr.toString(), "INCOMING_DB_USERS_LIST,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_DB_USERS_LIST, "", "", dbUsersList));
					return;
				}
				if(StringUtils.contains(event.data, GFSServerEvent.INCOMING_USER_PROPERTY_NAMES))
				{				
					arr = event.data.split("~");

					var dbPropertiesList:String = StringUtils.remove(arr.toString(), "INCOMING_USER_PROPERTY_NAMES,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_USER_PROPERTY_NAMES, "", "", dbPropertiesList));
					return;
				}
				if(StringUtils.contains(event.data, GFSServerEvent.INCOMING_GLOBAL_PROPERTY_NAMES))
				{				
					arr = event.data.split("~");

					var dbGlobalPropertiesList:String = StringUtils.remove(arr.toString(), "INCOMING_GLOBAL_PROPERTY_NAMES,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_GLOBAL_PROPERTY_NAMES, "", "", dbGlobalPropertiesList));
					return;
				}
				if(StringUtils.contains(event.data, GFSServerEvent.INCOMING_LAST_LOGIN_DATE))
				{				
					arr = event.data.split("~");

					var lastLogin:String = StringUtils.remove(arr.toString(), "INCOMING_LAST_LOGIN_DATE,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_LAST_LOGIN_DATE, "", "", lastLogin));
					return;
				}
				if(StringUtils.contains(event.data, GFSServerEvent.ACCOUNT_STATUS))
				{				
					arr = event.data.split("~");

					var accountStatus:String = StringUtils.remove(arr.toString(), "ACCOUNT_STATUS,", false)
					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.ACCOUNT_STATUS, "", accountStatus));
					return;
				}				
				if(StringUtils.contains(event.data, GFSServerEvent.SERVER_VERSION))			
				{								
					arr = event.data.split("~");
													
					dispatchEvent(new GFSServerEvent(GFSServerEvent.SERVER_VERSION, "", "", arr[1]));				
					return;
				}
				if(StringUtils.contains(event.data, GFSServerEvent.INCOMING_USERS_IP))			
				{								
					arr = event.data.split("~");							
					dispatchEvent(new GFSServerEvent(GFSServerEvent.INCOMING_USERS_IP, arr[1], "", arr[2]));				
					return;
				}
				//new
				if(StringUtils.contains(event.data, GFSServerEvent.MAP_DATA))
				{
					arr = event.data.split("~");					
					dispatchEvent(new GFSServerEvent(GFSServerEvent.MAP_DATA, "", "", arr[1]));
					return;
				}
				
				if(StringUtils.contains(event.data, USERPROPERTIES))
				{
					arr = event.data.split("~");
					trace("Toa Do "+arr[1] + arr[2]);
					dispatchEvent(new GFSServerEvent(GFSServerEvent.USERPROPERTIES, arr[1], "",arr[2]+"~"+arr[3]+"~"+arr[4]));
					return;
				}
				if(StringUtils.contains(event.data, PHONG))
				{
					arr = event.data.split("~");
					trace("Toa Do "+arr[1] + arr[2]);
					dispatchEvent(new GFSServerEvent(GFSServerEvent.USERPROPERTIES, "", "",arr[2]+"~"+arr[4]));
					return;
				}
				
				
			}
			catch(err:Error)
			{
				trace(err);
			}							
		}
		
		private function ioErrorHandler(event:IOErrorEvent):void
		{
			trace("ioErrorHandler: " + event);
			dispatchEvent(new GFSServerEvent(GFSServerEvent.ERROR_IO));
		}
				
		private function securityErrorHandler(event:SecurityErrorEvent):void
		{
			trace("securityErrorHandler: " + event);
			dispatchEvent(new GFSServerEvent(GFSServerEvent.ERROR_SECURITY));
		}
		public function requestMapdata(va:String)
		{
			socketSend(va+"~");
		}
		
		public function sendDetaiClick(user:String,x:String,y:String)
		{
			socketSend(USERPROPERTIES+"~"+user+"~"+ x + "~" + y);
			
		}
		public function sendStatusEvent(message:String):void
		{
			trace("sendStatusEvent: " + message);
			socketSend(BROADCAST_STATUS + "~" + message);
		}
		
		
		public function createBoard(messageText:String):void
		{
			socketSend(CREATE_BOARD + "~" + messageText);			
		}
		public function joinBoard(messageText:String):void
		{
			socketSend(JOIN_BOARD + "~" + messageText);
		}
		public function requestBoardList():void
		{
			socketSend(BOARD_LIST);
		}
		
	}
}